一个现代编译器的主要工作流程:源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 目标代码 (object code) → 链接器 (Linker) → 可执行程序 (executables)。
在预处理之前,编译器必须对该程序进行一些翻译处理。
1.1 编译器把源代码中出现的字符映射到源字符集。
该过程处理多字节字符和三宇符序列--字符扩展,让C更加国际化。
1.2 将物理换行转换成逻辑行
编译器定位每个反斜杠后面跟着换行符的实例, 并删除它们。也就是说, 把下面两个物理行(physical line):
printf("That's wond\ erful!\n");转换成一个逻辑行(logical line):
printf("That's wonderful!\n");
注意,在这种场合中,“换行符”的意思是通过按下Enter键在源代码文件中换行所生成的字符, 而不是指符号表征\n。
由于预处理表达式的长度必须是一个逻辑行, 所以这一步为预处理器做好了准备工作。一个逻辑行可以是多个物理行。
1.3 特殊文本序列的处理
编译器把文本划分成预处理记号序列、空白序列和注释序列(记号是由空格、制表符或换行符分隔的项)。这里要注意的是, 编译器将用一个空格字符替换每一条注释。因此,下面的代码:
int/*这看起来并不像一个空格*/fox;
将变成:
int fox;
而且,实现可以用一个空格替换所有的空白字符序列(不包括换行符)。
预处理器查找一行中以#号开始的预处理指令。预处理包括宏替换、文件包含、条件编译、以及其它的一些预处理指令(如pragma)。
编译器完成源代码到目标代码的转换。对于于强类型语言(如C语言)的编译器,其类型检查在编译阶段完成。
对于函数原型的声明,就是告诉编译器该函数的存在,也就是说,即使没有函数的定义,但有函数原型的声明,编译器也不会报错。当然,到了链接阶段,链接器会去查询函数的定义,此时就需要函数的定义了。
编译器将汇编或高级计算机语言源程序(Source program)作为输入,翻译成目标语言(Target language)机器代码的等价程序。源代码一般为高级语言 (High-level language), 如Pascal、C、C++、Java、汉语编程等或汇编语言,而目标则是机器语言的目标代码(Object code),有时也称作机器代码(Machine code)。
高级计算机语言便于人编写,阅读交流,维护。机器语言是计算机能直接解读、运行的。
对于C#、VB等高级语言而言,此时编译器完成的功能是把源码(SourceCode)编译成通用中间语言(MSIL/CIL)的字节码(ByteCode)。最后运行的时候通过通用语言运行库的转换,编程最终可以被CPU直接计算的机器码(NativeCode)。
链接器能够将各文件以及需要的库的代码全部链接到一起。
本页共39段,1528个字符,3345 Byte(字节)